package com.wl.cloud.security.component;

import cn.hutool.core.collection.CollUtil;
import com.wl.cloud.security.enums.SecurityErrorCode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;

import java.util.Collection;
import java.util.Iterator;

/**
 * @author: wanglin
 * @date: 2023-09-12 周二
 * @Version: 1.0
 * @Description: 动态权限决策管理器，用于判断用户是否有访问权限 1
 */
public class DynamicAccessDecisionManager implements AccessDecisionManager {

    public DynamicAccessDecisionManager() {
        System.out.println("init DynamicAccessDecisionManager...");
    }

    @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws InsufficientAuthenticationException {
        // 当接口未被配置资源时直接放行
        if (CollUtil.isEmpty(configAttributes)) {
            return;
        }

        Iterator<ConfigAttribute> iterator = configAttributes.iterator();
        while (iterator.hasNext()) {
            ConfigAttribute configAttribute = iterator.next();

            //将访问所需资源对应的角色和用户对应的角色进行比对
            String needAuthority = configAttribute.getAttribute();

            //访问的路径没有分配角色权限，则默认只有管理员可以访问
            if (StringUtils.isBlank(needAuthority)) {
                return;
            }

            //遍历用户拥有的角色类型
            boolean isMatchFlag = authentication.getAuthorities().stream().map(e -> e.getAuthority()).anyMatch(x -> needAuthority.trim().equals(x));
            if (isMatchFlag) {
                return;
            } else {
                throw new AccessDeniedException(SecurityErrorCode.UNAUTHORIZED.getDescription());
            }
        }
        throw new AccessDeniedException(SecurityErrorCode.UNAUTHORIZED.getDescription());
    }

    @Override
    public boolean supports(ConfigAttribute configAttribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}